//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package dev_container_dao

import (
	"context"
	"fmt"
	"strings"

	"atomgit.com/openlinksaas/api-server/dao/db_ns"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

type PkgVerDbItem struct {
	PkgVerId string `bson:"_id"`
	PkgName  string `bson:"pkgName"`
	Version  string `bson:"version"`
}

type _PkgVerDao struct {
	mc *mongo.Collection
}

func newPkgVerDao(db *mongo.Database) (*_PkgVerDao, error) {
	mc := db.Collection(db_ns.DB_NS_DEV_CONTAINER + "pkg_ver")
	_, err := mc.Indexes().CreateOne(context.Background(), mongo.IndexModel{
		Keys: bson.D{{"pkgName", 1}},
	})
	if err != nil {
		return nil, err
	}
	return &_PkgVerDao{mc: mc}, nil
}

func (db *_PkgVerDao) Insert(ctx context.Context, dbItem *PkgVerDbItem) error {
	dbItem.PkgVerId = db.genPkgVerId(dbItem.PkgName, dbItem.Version)
	_, err := db.mc.InsertOne(ctx, dbItem)
	return err
}

func (db *_PkgVerDao) genPkgVerId(pkgName, version string) string {
	tmpList := []string{}
	for _, verPart := range strings.Split(version, ".") {
		verPartLen := len(verPart)
		if verPartLen == 0 {
			tmpList = append(tmpList, "00000")
		} else if verPartLen == 1 {
			tmpList = append(tmpList, "0000"+verPart)
		} else if verPartLen == 2 {
			tmpList = append(tmpList, "000"+verPart)
		} else if verPartLen == 3 {
			tmpList = append(tmpList, "00"+verPart)
		} else if verPartLen == 4 {
			tmpList = append(tmpList, "0"+verPart)
		} else {
			tmpList = append(tmpList, verPart)
		}
	}
	return fmt.Sprintf("%s:%s", pkgName, strings.Join(tmpList, "."))
}

func (db *_PkgVerDao) Exist(ctx context.Context, pkgName, version string) (bool, error) {
	pkgVerId := db.genPkgVerId(pkgName, version)
	count, err := db.mc.CountDocuments(ctx, bson.M{"_id": pkgVerId})
	return count > 0, err
}

func (db *_PkgVerDao) Remove(ctx context.Context, pkgName, version string) error {
	pkgVerId := db.genPkgVerId(pkgName, version)
	_, err := db.mc.DeleteOne(ctx, bson.M{"_id": pkgVerId})
	return err
}

func (db *_PkgVerDao) RemoveAll(ctx context.Context) error {
	_, err := db.mc.DeleteMany(ctx, bson.M{})
	return err
}

func (db *_PkgVerDao) Count(ctx context.Context, pkgName string) (uint32, error) {
	count, err := db.mc.CountDocuments(ctx, bson.M{"pkgName": pkgName})
	return uint32(count), err
}

func (db *_PkgVerDao) ListByPkgName(ctx context.Context, pkgName string) ([]*PkgVerDbItem, error) {
	cursor, err := db.mc.Find(ctx, bson.M{"pkgName": pkgName}, options.Find().SetSort(bson.M{"_id": -1}))
	if err != nil {
		return nil, err
	}
	retList := []*PkgVerDbItem{}
	err = cursor.All(ctx, &retList)
	return retList, err
}
